<?php

namespace app\admin\controller\pt;

use app\common\controller\Backend;
use Exception;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
use app\common\library\Export as ExportLib;
use think\Db;
use think\exception\PDOException;
use think\exception\ValidateException;
use app\admin\model\pt\DutyList as DutyModel;
use app\admin\model\pt\Person as PersonModel;
use app\admin\model\pt\LaborAdmin as LaborAdminModel;
use app\admin\model\pt\Labor as LaborModel;
use app\common\library\Duty as DutyLib;
use app\common\library\Salary as SalaryLib;
use app\admin\library\Auth;

/**
 * 人员信息管理
 *
 * @icon fa fa-circle-o
 */
class Person extends Backend
{

    /**
     * Person模型对象
     * @var \app\admin\model\pt\Person
     */
    protected $model = null;
    // 劳务公司账号免除的权限
    protected $noNeedRight = ['viewJob', 'deljob', 'batch', 'workBatchAdd'];

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\pt\Person;
        $this->view->assign("sexList", $this->model->getSexList());
        $this->view->assign("userTypeList", $this->model->getUserTypeList());
        $this->view->assign("whiteBlackList", $this->model->getWhiteBlackList());
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */

    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $laborId = $this->getLaborId();
            $list = $this->model
                ->where($where);
            if (!empty($laborId)) {
                $list = $list->where('pt_labor_id', $laborId);
            }
            $list = $list->with(['job', 'depart', 'labor'])
                ->order($sort, $order)
                ->paginate($limit);

            $rows = $list->items();

            $result = array("total" => $list->total(), "rows" => $rows);

            return json($result);
        }
        return $this->view->fetch();
    }

    public function batch()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax()) {
            $filter = $this->request->get('filter');
            $filter = json_decode($filter, true);
            if (empty($filter['start']) || empty($filter['end'])) {
                $result = array("total" => 0, "rows" => []);
            } else {
                $auth = Auth::instance();
                $adminName = $auth->isLogin() ? $auth->username : __('Unknown');
                $adminId = $auth->isLogin() ? $auth->id : 0;
                // 查找是否劳务公司
                $laborAdmin = LaborAdminModel::where('admin_id', $adminId)->find();
                $laborId = 0;
                if ($laborAdmin) {
                    $laborId = $laborAdmin->pt_labor_id;
                }

                $personIds = [];
                // 先查出对应时间区间有安排工作的人员ID
                if (isset($filter['start']) && isset($filter['end'])) {
                    $start = str_replace('-', '', $filter['start']);
                    $end = str_replace('-', '', $filter['end']);
                    $plans = DutyModel::where('date_id', '>=', $start)->where('date_id', '<=', $end)->select();
                    foreach ($plans as $p) {
                        $personIds[] = $p->pt_person_id;
                    }
                }
                $limit = 1000;
                $list = $this->model;
                if (!empty($personIds)) {
                    $list = $list->where('id', 'not in', $personIds);
                }
                if (!empty($filter['whiteblack'])) {
                    $list = $list->where('white_black', $filter['whiteblack']);
                }
                if ($laborId) {
                    $list = $list->where('pt_labor_id', $laborId);
                }
                $list = $list->with(['labor'])
                    ->order('id', 'asc')
                    ->paginate($limit);

                $rows = $list->items();

                $result = array("total" => $list->total(), "rows" => $rows);
            }

            return json($result);
        }
        $jobId = $this->request->get('jobId', 0);
        $date = $this->request->get('date', '');
        $close = $this->request->get('close', '');
        $this->view->assign('jobId', $jobId);
        $this->view->assign('date', $date);
        $this->view->assign('close', $close);
        return $this->view->fetch();
    }

    public function viewJob()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        $jobId = $this->request->get('jobId', 0);
        $date = $this->request->get('date', '');
        if ($this->request->isAjax()) {
            // 先查出对应时间区间有安排工作的人员ID
            if (empty($jobId) || empty($date)) {
                $result = array("total" => 0, "rows" => []);
            } else {
                $auth = Auth::instance();
                $adminName = $auth->isLogin() ? $auth->username : __('Unknown');
                $adminId = $auth->isLogin() ? $auth->id : 0;
                // 查找是否劳务公司
                $laborAdmin = LaborAdminModel::where('admin_id', $adminId)->find();
                $laborId = 0;
                if ($laborAdmin) {
                    $laborId = $laborAdmin->pt_labor_id;
                }

                $dateId = date('Ymd', strtotime($date));
                $plans = DutyModel::where('date_id', $dateId)->where('pt_job_id', $jobId)->select();
                $personIds = [];
                foreach ($plans as $p) {
                    $personIds[] = $p->pt_person_id;
                }
                $limit = 1000;
                $list = $this->model;
                $list = $list->where('id', 'in', $personIds);
                if ($laborId) {
                    $list = $list->where('pt_labor_id', $laborId);
                }
                $list = $list->with(['labor'])
                    ->order('id', 'asc')
                    ->paginate($limit);

                $rows = $list->items();

                $result = array("total" => $list->total(), "rows" => $rows);

            }
            return json($result);
        }
        $this->view->assign('jobId', $jobId);
        $this->view->assign('date', $date);
        return $this->view->fetch();
    }

    public function delJob($ids = null)
    {
        if (!$this->request->isPost()) {
            $this->error(__("Invalid parameters"));
        }
        $jobId = $this->request->get('jobId');
        $date = $this->request->get('date');
        $ids = $ids ? $ids : $this->request->post("ids");
        if ($ids) {
            $dateId = date('Ymd', strtotime($date));
            $curDateId = date('Ymd');
            if ($dateId < $curDateId) {
                $this->error('不能删除小于当前日期的工作安排');
            }
            $model = new DutyModel();
            $adminIds = $this->getDataLimitAdminIds();
            if (is_array($adminIds)) {
                $model->where($this->dataLimitField, 'in', $adminIds);
            }
            $list = $model->where('pt_person_id', 'in', $ids)
                          ->where('pt_job_id', $jobId)
                          ->where('date_id', $dateId)
                          ->select();

            $count = 0;
            Db::startTrans();
            try {
                $dutyLib = new DutyLib();
                foreach ($list as $k => $v) {
                    $person = PersonModel::get($v->pt_person_id);
                    $dutyLib->handleLaborLog($person, $v->pt_depart_id, $v->pt_job_id, $dateId, $v->depart_name, $v->job_name, 'del');
                    $count += $v->delete();
                }
                if ($count) {
                    // 重新计算消耗的
                    $dutyLib->calDutyTotal($jobId, 0, $dateId);
                    // 删除工作 
                    $salaryLib = new SalaryLib();
                    $salaryLib->delSalary($ids, $dateId, $jobId);
                }
                Db::commit();
            } catch (PDOException $e) {
                Db::rollback();
                $this->error($e->getMessage());
            } catch (Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
            if ($count) {
                $this->success();
            } else {
                $this->error(__('No rows were deleted'));
            }
        }
        $this->error(__('Parameter %s can not be empty', 'ids'));
    }



    public function add()
    {
        $laborId = $this->getLaborId();
        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                $params = $this->preExcludeFields($params);

                if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
                    $params[$this->dataLimitField] = $this->auth->id;
                }
                $result = false;
                Db::startTrans();
                try {
                    //是否采用模型验证
                    if ($this->modelValidate) {
                        $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
                        $this->model->validateFailException(true)->validate($validate);
                    }
                    $params['phone'] = !empty($params['phone']) ? trim($params['phone']) : '';
                    $params['id_card'] = !empty($params['id_card']) ? trim($params['id_card']) : '';
                    $params['user_name'] = !empty($params['user_name']) ? trim($params['user_name']) : '';
                    // 人员重复以身份证和手机
                    $phone = $params['phone'];
                    if (!empty($phone)) {
                        $checkPerson = $this->model->where('phone', $phone)->find();
                        if ($checkPerson) {
                            throw new Exception('手机号重复');
                        }
                    }
                    $idCard = $params['id_card'];
                    if (!empty($idCard)) {
                        $checkPerson = $this->model->where('id_card', $idCard)->find();
                        if ($checkPerson) {
                            throw new Exception('身份证号重复');
                        }
                    }
                    $params['confirm_idcard'] = '1';
                    $params['confirm_desc'] = '后台录入';
                    if ($laborId) {
                        $params['pt_labor_id'] = $laborId;
                    }
                    $result = $this->model->allowField(true)->save($params);
                    Db::commit();
                } catch (ValidateException $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                } catch (PDOException $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                } catch (Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
                if ($result !== false) {
                    $this->success();
                } else {
                    $this->error(__('No rows were inserted'));
                }
            }
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $this->view->assign('labor_id', $laborId);
        return $this->view->fetch();
    }

    /**
     * 编辑
     */
    public function edit($ids = null)
    {
        $row = $this->model->get($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds)) {
            if (!in_array($row[$this->dataLimitField], $adminIds)) {
                $this->error(__('You have no permission'));
            }
        }

        $laborId = $this->getLaborId();

        if ($this->request->isPost()) {
            $params = $this->request->post("row/a");
            if ($params) {
                $params = $this->preExcludeFields($params);
                $result = false;
                Db::startTrans();
                try {
                    //是否采用模型验证
                    if ($this->modelValidate) {
                        $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
                        $row->validateFailException(true)->validate($validate);
                    }
                    $params['phone'] = !empty($params['phone']) ? trim($params['phone']) : '';
                    $params['id_card'] = !empty($params['id_card']) ? trim($params['id_card']) : '';
                    $params['user_name'] = !empty($params['user_name']) ? trim($params['user_name']) : '';
                    // 人员重复以身份证和手机
                    $phone = $params['phone'];
                    if (!empty($phone)) {
                        $checkPerson = $this->model->where('phone', $phone)->where('id', '<>', $ids)->find();
                        if ($checkPerson) {
                            throw new Exception('手机号重复');
                        }
                    }
                    $idCard = $params['id_card'];
                    if (!empty($idCard)) {
                        $checkPerson = $this->model->where('id_card', $idCard)->where('id', '<>', $ids)->find();
                        if ($checkPerson) {
                            throw new Exception('身份证号重复');
                        }
                    }
                    $result = $row->allowField(true)->save($params);
                    Db::commit();
                } catch (ValidateException $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                } catch (PDOException $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                } catch (Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }
                if ($result !== false) {
                    $this->success();
                } else {
                    $this->error(__('No rows were updated'));
                }
            }
            $this->error(__('Parameter %s can not be empty', ''));
        }
        $this->view->assign('labor_id', $laborId);
        $this->view->assign("row", $row);
        return $this->view->fetch();
    }

    public function export()
    {
        $this->request->filter(['strip_tags', 'trim']);
        list($where, $sort, $order, $offset, $limit) = $this->buildparams();
        $limit = 1000;
        $list = $this->model
            ->where($where)
            ->with(['job', 'depart', 'labor'])
            ->order('id', 'asc')
            ->paginate($limit);

        $rows = $list->items();

        $persons = [];
        foreach ($rows as $r) {
            $persons[] = [
                $r->user_name,
                $r->id_card,
                $this->model->getSexTextAttr($r->sex, null),
                $r->phone,
                $this->model->getUserTypeTextAttr($r->user_type, null),
                empty($r->depart) ? '-' : $r->depart->name,
                empty($r->job) ? '-' : $r->job->name,
                empty($r->labor) ? '-' : $r->labor->name,
                $r->user_id ? '已关联' : '未关联',
                $this->model->getConfirmIdCardTextAttr($r->confirm_idcard, null),
                $this->model->getStatusTextAttr($r->status, null),
                empty($r->duty_date) ? '-' : $r->duty_date,
                $this->model->getWhiteBlackTextAttr($r->white_black, null),
            ];
        }

        $savePath = '/uploads/export/'.date('Ymd') ;
        $filename =  '人员信息_' . uniqid() .'.xlsx';
        $filePath = ROOT_PATH . 'public' . $savePath;
        $fileSaveName =  $filePath  . '/' . $filename;
        if (!is_dir($filePath)) {
            @mkdir($filePath, 0755, true);
        }
        $headers = [
            '姓名',
            '身份证',
            '性别',
            '联系电话',
            '人员类别',

            '当前所属部门',
            '当前所属岗位',
            '劳务公司',
            '关联微信号',

            '实名状态',
            '人员状态',
            '实际入职日期',
            '黑白名单',

        ];
        $exportLib = new ExportLib($headers, $persons, $fileSaveName, 'save');
        $exportLib->createTable();
        $this->success('导出成功', '', ['file' => cdnurl($savePath . '/' .$filename, true)]);
    }

    public function import()
    {
        if ($this->request->isPost()) {
            $res = [
                'msg' => '全部导入成功',
                'err' => [
                    // '第一行手机号重复', 
                    // '第三行身份证重复',
                ],
            ];
            $file = $this->request->post('person_file');
            $filePath = ROOT_PATH . 'public' . $file;
            if (!is_file($filePath)) {
                $this->error(__('文件不存在'));
            }
            //实例化reader
            $ext = pathinfo($filePath, PATHINFO_EXTENSION);
            if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
                $this->error(__('Unknown data format'));
            }
            if ($ext === 'csv') {
                $file = fopen($filePath, 'r');
                $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
                $fp = fopen($filePath, "w");
                $n = 0;
                while ($line = fgets($file)) {
                    $line = rtrim($line, "\n\r\0");
                    $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
                    if ($encoding != 'utf-8') {
                        $line = mb_convert_encoding($line, 'utf-8', $encoding);
                    }
                    if ($n == 0 || preg_match('/^".*"$/', $line)) {
                        fwrite($fp, $line . "\n");
                    } else {
                        fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
                    }
                    $n++;
                }
                fclose($file) || fclose($fp);

                $reader = new Csv();
            } elseif ($ext === 'xls') {
                $reader = new Xls();
            } else {
                $reader = new Xlsx();
            }

            //加载文件
            $insert = [];
            try {
                if (!$PHPExcel = $reader->load($filePath)) {
                    $this->error(__('Unknown data format'));
                }
                $currentSheet = $PHPExcel->getSheet(0);  //读取文件中的第一个工作表
                $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号
                $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
                $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
                $fields = [];
                // 表头
                for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
                    for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                        $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                        $fields[] = $val;
                    }
                }
                // 数据
                for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
                    $values = [];
                    for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                        $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                        $values[] = is_null($val) || empty($val) || trim($val) == '-' ? '' : trim($val);
                    }
                    // var_dump($values);
                    $isInsert = 0;
                    // 检查数据
                    $name = trim($values[0]);
                    $idCard = trim($values[1]);
                    $phone = trim($values[3]);
                    if (empty($name) || empty($idCard) || empty($phone)) {
                        $res['err'][] = '第' . $currentRow . '行重要信息缺失, 如:姓名，身份证，手机号';
                        continue;
                    }
                    // 检查身份证号是否重复
                    $model = $this->model->where('id_card', $idCard)->find();
                    if ($model) {
                        $res['err'][] = '第' . $currentRow . '行身份信息重复';
                        continue;
                    }
                    // 检查手机号
                    $model = $this->model->where('phone', $phone)->find();
                    if ($model) {
                        $res['err'][] = '第' . $currentRow . '行手机号重复';
                        continue;
                    }

                    $sex = $values[2];
                    if ($sex == '男') {
                        $sex = '1';
                    } else if ($sex == '女') {
                        $sex = '2';
                    } else {
                        $sex = '0';
                    }

                    $userType = $values[4];
                    if ($userType == '自招兼职') {
                        $userType = 'self';
                    } else if ($userType == '实习生') {
                        $userType = 'intern';
                    } else if ($userType == '劳务公司'){
                        $userType = 'labor';
                    } else {
                        $userType = 'self';
                    }
                    $laborName = $values[5];
                    $laborId = $this->getLaborId();
                    // 如果是劳务公司需要检查劳务公司信息是否正确
                    if (empty($laborId) && $userType == 'labor') {
                        if (empty($laborId))
                        $laborInfo = LaborModel::where('name', 'like', '%'.$laborName.'%')->find();
                        if (!$laborInfo) {
                            $res['err'][] = '第' . $currentRow . '行劳务公司名称在系统中未找到';
                            continue;
                        }
                        $laborId = $laborInfo->id;
                    }

                    $dutyDate = $values[6];
                    $bankcode = $values[7];
                    $bankname = $values[8];
                    $insert[] = [
                        'source'  => 'backend',
                        'confirm_idcard' => '1',
                        'confirm_desc' => '后台导入',
                        'user_name' => $name,
                        'sex' => $sex,
                        'phone' => $phone,
                        'user_type' => $userType,
                        'duty_date' => empty($dutyDate) ? null : $dutyDate,
                        'bank_code' => empty($bankcode) ? null : $bankcode,
                        'bank_openname' => empty($bankname) ? null : $bankname,
                        'id_card' => $idCard,
                        'pt_labor_id' => $laborId,
                    ];
                }
                /*
                var_dump($insert);
                var_dump($res);
                exit;
                */
            } catch (Exception $exception) {
                $this->error($exception->getMessage());
            }
            if (!$insert) {
                $res['msg'] = '未导入数据，错误如下';
                $this->success('导入成功', null, $res);
            }

            try {
                $this->model->saveAll($insert);
            } catch (PDOException $exception) {
                $msg = $exception->getMessage();
                if (preg_match("/.+Integrity constraint violation: 1062 Duplicate entry '(.+)' for key '(.+)'/is", $msg, $matches)) {
                    $msg = "导入失败，包含【{$matches[1]}】的记录已存在";
                };
                $this->error($msg);
            } catch (Exception $e) {
                $this->error($e->getMessage());
            }
            if (!empty($res['err'])) {
                $res['msg'] = '部分导入成功';
            }
            $this->success('导入成功', null, $res);
        }
        $templateFile = cdnurl('/template/人员信息_导入模版.xlsx', true);
        $this->view->assign('template_file', $templateFile);
        return $this->view->fetch();
         
    }

    private function changeSalaryStage($salaryStage)
    {
        $arr = json_decode($salaryStage, true);
        $stage = '';
        if (empty($arr)) {
            $stage = '未设置';
        } else {
            foreach ($arr as $a) {
                $stage .= "起始：" . $a['start'] . ", 结束：" . $a['end'] . ", 工资：" . $a['salary'] . "<br />";
            }
        }

        return $stage;
    }

    private function getLaborId()
    {
        $auth = Auth::instance();
        $adminName = $auth->isLogin() ? $auth->username : __('Unknown');
        $adminId = $auth->isLogin() ? $auth->id : 0;
        // 查找是否劳务公司
        $laborAdmin = LaborAdminModel::where('admin_id', $adminId)->find();
        $laborId = 0;
        if ($laborAdmin) {
            $laborId = $laborAdmin->pt_labor_id;
        }

        return $laborId;
    
    }

}
